<!--
/**
* @author xuyh0817
* @email xuyh0817@foxmail.com
* @date 2022-02-18 23:58
* @version 2.0.0
* @doc todo
* @website todo
* @remark  如果要分发源码，需在本文件顶部保留此文件头信息！！
*/
-->
<template>
  <div class="x-render-left-list">
    <!-- 搜索 -->
    <div class="x-render-left-header x-render-component-searcher">
      <a-input
        v-model.trim="keyword"
        allowClear
        placeholder="请输入关键字查找组件"
      >
        <a-icon type="search" slot="prefix"/>
      </a-input>
    </div>
    <perfect-scrollbar ref="scroll" class="x-render-scrollarea">
      <!-- 组件列表 -->
      <a-collapse accordion @change="collapseChangeHandler">
        <template v-for="item in collapsePanelRenderComponents">
          <a-collapse-panel :key="item.code" :header="item.name">
            <!--   name：设置组名称为 XRenderForm，相同组名称之间可以完成拖拽添加
                  pull: 'clone' 会触发 :clone="handleAddFormItem"
                      :group="{ name: 'XRenderForm', pull: 'clone', put: false }"-->
            <vue-draggable
              :clone="addFormItemHandler"
              :group="{ name: 'XRenderForm', pull: 'clone', put: false }"
              :list="item.children"
              :sort="false"
              class="x-render-component-group"
              handle=".x-render-component-item"
              tag="ul"
            >
              <li
                v-for="comp of item.children"
                :key="item.code + '-' + comp.type"
                class="x-render-component-item"
              >
                <div class="x-render-component-title">{{ comp.type.startsWith('XRender') ? comp.type.substring(7) : comp.type  }}</div>
                <div>{{ comp.name }}</div>
              </li>
            </vue-draggable>
          </a-collapse-panel>
        </template>
      </a-collapse>
    </perfect-scrollbar>
  </div>
</template>

<script>
import { cloneDeep } from 'lodash'
import { randomString } from '../../../../../libs/utils'

// 固定的布局组件
const CollapseItems = [
  {
    name: '基础组件',
    code: 'baseComponent',
    children: []
  },
  {
    name: '布局组件',
    code: 'layoutComponent',
    children: []
  }
]

export default {
  name: 'XDesignFormLeftCoomponentList',
  inject: ['xDesignForm'],
  data() {
    return {
      // 查询的字段
      keyword: ''
    }
  },
  computed: {
    // 组件支持模糊搜索
    filteredRenderComponents: {
      get() {
        const { keyword, flatRenderComponents } = this
        return keyword
          ? flatRenderComponents.filter((item) => (!!item.name && item.name.includes(keyword)) || (!!item.type && item.type.includes(keyword)))
          : flatRenderComponents
      }
    },
    // 扁平组件对象
    flatRenderComponents: {
      get() {
        const { xDesignForm } = this
        const { sortedRenderComponents } = xDesignForm
        const comps = []
        for (const { baseInfo } of sortedRenderComponents) {
          const container = baseInfo.container || {}
          comps.push({
            type: baseInfo.code,
            name: baseInfo.name,
            containerCode: container.code,
            containerName: container.name
          })
        }
        return comps
      }
    },
    // 计算折叠组件
    collapsePanelRenderComponents: {
      get() {
        // 设置固定的组件菜单
        const collapseArr = [...cloneDeep(CollapseItems)]
        const { filteredRenderComponents } = this
        for (const item of filteredRenderComponents) {
          if (!item.containerCode) {
            continue
          }
          const result = collapseArr.find(container => container.code === item.containerCode)
          if (!result) {
            collapseArr.push({
              name: item.containerName,
              code: item.containerCode,
              children: [item]
            })
          } else {
            const children = result['children']
            children.splice(children.length, 0, item)
          }
        }

        return collapseArr
      }
    }
  },
  methods: {
    /**
     * 获取表单模板对象
     * config 中对应的属性  {@link flatRenderComponents 计算属性}
     *  type: baseInfo.code,
     *  name: baseInfo.name,
     */
    getTemplateByType({ type, name }) {
      const { xDesignForm } = this
      const templatesMap = xDesignForm.templatesMap || {}
      if (!templatesMap.hasOwnProperty(type)) {
        throw new Error(`未注册此类${name}:${type}组件`)
      }
      const option = cloneDeep(templatesMap[type])
      // 设置id
      option.id = randomString()
      // 布局项直接返回
      if (option.isLayout) {
        return option
      }
      option.formItem.prop = 'key_' + Date.now()
      return option
    },
    /**
     * 拖拽后新增表单项
     * config 中对应的属性  {@link flatRenderComponents 计算属性}
     *  type: baseInfo.code,
     *  name: baseInfo.name,
     *  containerCode: container.code,
     *  containerName: container.name
     *
     * @param config 组件属性
     * @returns Object 组件模板对象
     */
    addFormItemHandler(config) {
      return this.getTemplateByType(config)
    },
    // 切换时，进行设置滚动条 滚到到顶端
    collapseChangeHandler() {
      this.$refs.scroll.$el.scrollTop = 0
    }
  }
}
</script>

<style lang="css" scoped>
.x-render-left-list{
  width: 260px;
  min-width: 130px;
  padding: 0 4px;
}

/* 头部区域 */
.x-render-left-list .x-render-left-header {
  height: 50px;
  line-height: 50px;
  border-bottom: 1px solid #eeeeee;
}

/* 搜索框 */
.x-render-left-list .x-render-component-searcher {
  padding: 5px 10px;
}

/* 组件列表 */
.x-render-left-list .x-render-component-group {
  padding: 0;
  margin: 0;
}

/* 单个组件 */
.x-render-component-group > .x-render-component-item {
  width: 115px;
  line-height: 1.5em;
  color: #606266;
  border: 1px solid #ebeef5;
  overflow: hidden;
  cursor: move;
  white-space: nowrap;
  display: inline-block;
  text-overflow: ellipsis;
  border-radius: 3px;
  padding: 6px 8px;
  box-sizing: border-box;
  margin: 5px;
  font-size: 12px;
}

/* 组件标题 */
.x-render-component-item > .x-render-component-title {
  font-weight: bold;
  color: #222;
}

/* 滚动区域 */
.x-render-left-list .x-render-scrollarea {
  /* 减去头部的高度 */
  height: calc(100vh - 145px);
}

/deep/ .ant-collapse-header {
  padding: 8px 16px !important;
  padding-left: 40px !important;
}

/deep/ .ant-collapse-content-box {
  padding: 0 !important;
  margin: 0 !important;
}
</style>
